<template>
  <drag-dialog title="接口配置" v-model="visible">
    <el-collapse v-model="active">
      <el-collapse-item title="接口配置" name="0">
        <el-form label-position="right" label-width="100px" label-suffix=":">
          <el-form-item label="选择模型" v-if="type == 'model'">
            <el-select v-model="localData.model" clearable style="width: 400px" @change="generateUrlByModelApi">
              <el-option v-for="opt in ajaxModelList" :key="opt.modelEntityCode" :label="`${opt.modelEntityDesc}(${opt.modelEntityCode})`" :value="opt.modelEntityCode" />
            </el-select>
          </el-form-item>
          <el-form-item label="选择方法" v-if="type == 'model'">
            <el-select v-model="localData.api" clearable style="width: 400px" @change="generateUrlByModelApi">
              <el-option v-for="opt in ajaxApiList" :key="opt.dictValue" :label="`${opt.dictLabel}(${opt.dictValue})`" :value="opt.dictValue" />
            </el-select>
          </el-form-item>
          <el-form-item label="请求地址">
            <el-tag v-if="type == 'model'">{{ localData.interfaceUrl }}</el-tag>
            <api-selector v-else v-model="localData.interfaceUrl" @update="handleRegApiUpdate" />
          </el-form-item>
        </el-form>
      </el-collapse-item>
      <el-collapse-item title="入参绑定" name="1">
        <template #title>
          <span>入参绑定</span>
          <span class="tips">tips: 指定调用接口时需要传入的流程参数</span>
        </template>
        <text-add-button @click="addInParam" />
        <el-table :data="localData.params" border>
          <el-table-column align="center" prop="elementName" label="参数名称">
            <template #default="scope">
              <el-input v-model="scope.row.elementName" placeholder="请输入参数名称" />
            </template>
          </el-table-column>
          <el-table-column align="center" prop="description" label="参数描述">
            <template #default="scope">
              <el-input v-model="scope.row.description" placeholder="请输入参数描述" />
            </template>
          </el-table-column>
          <el-table-column align="center" prop="from" label="从流程变量读取">
            <template #default="scope">
              <el-select v-model="scope.row.from" clearable>
                <el-option v-for="opt in globalVariables" :key="opt.id" :label="opt.name" :value="opt.id" />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column align="center" label="操作" width="100">
            <template #default="scope">
              <text-delete-button @click="deleteInParam(scope.$index)" />
            </template>
          </el-table-column>
        </el-table>
      </el-collapse-item>
      <el-collapse-item title="出参绑定" name="2">
        <template #title>
          <span>出参绑定</span>
          <span class="tips">tips: 将接口返回的数据保存到指定的流程参数中</span>
        </template>
        <text-add-button @click="addOutParam" />
        <el-table :data="localData.outputVariables" border>
          <el-table-column align="center" prop="to" label="输出到流程变量">
            <template #default="scope">
              <el-select v-model="scope.row.to" clearable>
                <el-option v-for="opt in globalVariables" :key="opt.id" :label="opt.name" :value="opt.id" />
              </el-select>
            </template>
          </el-table-column>
          <el-table-column align="center" prop="jsonpath" label="JSONPath表达式">
            <template #default="scope">
              <el-input v-model="scope.row.jsonpath" placeholder="请输入JSONPath表达式" />
            </template>
          </el-table-column>
          <el-table-column align="center" label="操作" width="100">
            <template #default="scope">
              <text-delete-button @click="deleteOutParam(scope.$index)" />
            </template>
          </el-table-column>
        </el-table>
        <div>出参列表:</div>
        <el-table :data="paramOutList" row-key="elementName" border>
          <el-table-column align="center" prop="elementName" label="名称" />
          <el-table-column align="center" prop="description" label="描述" />
          <el-table-column align="center" prop="elementType" label="类型" />
          <el-table-column align="center" label="操作" width="100">
            <template #default="scope">
              <text-add-button text="选择" @click="handleParamOutSelect(scope.row)" />
            </template>
          </el-table-column>
        </el-table>
      </el-collapse-item>
    </el-collapse>
    <template #footer>
      <dialog-footer @ok="submit" @cancel="cancel" />
    </template>
  </drag-dialog>
</template>
  
  <script lang="ts">
import { defineComponent } from 'vue';
import { mapState } from 'pinia';
import modelerStore from '@wf/components/bpmnjs/store/modeler';
import { getGlobalVariablesValue } from '../../bo-utils/globalVariablesUtil';
import { searchModel } from '@code/api/code/model/info';
import { getCacheDict } from '@/platform/base/api/base/dict/type';
import { getModelApiInAndOutParams, getRegisterApiInAndOutParams } from './api';
import { cloneDeep } from 'lodash-es';

export default defineComponent({
  name: 'ServiceTaskDocSetting',
  props: {
    modelValue: {
      type: Boolean,
      default: false
    },
    data: {
      type: Object,
      default: () => {}
    },
    type: {
      type: String,
      default: 'model'
    }
  },
  data() {
    return {
      visible: false,
      localData: {},
      globalVariables: [], // 流程全局变量,
      active: ['0'],
      ajaxModelList: [],
      ajaxApiList: [],
      paramInList: [],
      paramOutList: [
        {
          elementName: 'info',
          elementType: 'object',
          description: '',
          children: [
            {
              elementName: 'name',
              elementType: 'string',
              description: '',
              children: [
                {
                  elementName: 'main',
                  elementType: 'string',
                  description: ''
                }
              ]
            },
            {
              elementName: 'age',
              elementType: 'number',
              description: ''
            }
          ]
        }
      ]
    };
  },
  computed: {
    ...mapState(modelerStore, ['getActive', 'getActiveId'])
  },
  watch: {
    modelValue: {
      handler(newVal) {
        this.visible = newVal;
        if (newVal) {
          this.localData = cloneDeep(this.data);
        }
      },
      immediate: true
    },
    visible: {
      handler(newVal) {
        this.$emit('update:modelValue', newVal);
      }
    }
  },
  mounted() {
    this.initData();
  },
  methods: {
    initData() {
      this.globalVariables = getGlobalVariablesValue(this.getActive.businessObject.$parent);
      this.searchAjaxModel();
      this.searchAjaxApi();
    },
    searchAjaxModel() {
      return searchModel().then((res) => {
        this.ajaxModelList = res.data;
      });
    },
    searchAjaxApi() {
      getCacheDict('uni_mda_rest').then((response) => {
        this.ajaxApiList = response.data;
      });
    },
    generateUrlByModelApi() {
      this.localData.interfaceUrl = `/uni/mda/${this.localData.model}/${this.localData.api}`;
      this.getModelApiParams();
    },
    getModelApiParams() {
      if (this.localData.model && this.localData.api) {
        return getModelApiInAndOutParams(this.localData.model, this.localData.api).then((res) => {
          this.paramInList = res.data.inParams;
          this.paramOutList = res.data.outParams;
          this.localData.params = this.paramInList;
        });
      }
    },
    handleRegApiUpdate(data) {
      const { apiId, apiVersion, apiVerId } = data;
      if (apiId) {
        return getRegisterApiInAndOutParams(apiId, apiVersion, apiVerId).then((res) => {
          this.paramInList = res.data.inParams;
          this.paramOutList = res.data.outParams;
          this.localData.params = this.paramInList;
        });
      }
    },
    handleParamOutSelect(row) {
      const { elementName } = row;
      const paths = this.findValuePaths(this.paramOutList, elementName);
      const jsonpath = this.generateJsonPath(paths);
      this.localData.outputVariables.push({ to: '', jsonpath });
    },
    // 寻找值路径
    findValuePaths(obj, value) {
      let paths = [];

      function search(obj, path, value) {
        obj.map((item) => {
          const { elementName, children } = item;
          let currentPath = path;
          if (children && children.length) {
            currentPath = path.concat(elementName);
            search(children, currentPath, value);
          }
          if (elementName == value) {
            currentPath = path.concat(elementName);
            paths.push(currentPath);
          }
        });
      }

      search(obj, [], value);
      return paths.filter((p) => p.length);
    },
    // 根据选择的出参字段生成jsonpath表达式
    generateJsonPath(paths) {
      if (paths && paths.length) {
        return '$.' + paths[0].join('.');
      }
    },
    addInParam() {
      this.localData.params.push({ name: '', desc: '', from: '' });
    },
    deleteInParam(index: number) {
      this.localData.params.splice(index, 1);
    },
    addOutParam() {
      this.localData.outputVariables.push({ to: '', jsonpath: '' });
    },
    deleteOutParam(index: number) {
      this.localData.outputVariables.splice(index, 1);
    },
    submit() {
      if (!this.localData.interfaceUrl) {
        this.msgError('请配置接口地址！');
        return;
      }
      this.$emit('submit', this.localData);
      this.cancel();
    },
    cancel() {
      this.visible = false;
    }
  }
});
</script>
  
<style lang="scss" scoped>
.tips {
  margin-left: 40px;
  color: #7f7f7f;
}
</style>